﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using INSTA.BankApplication.Engine;
using NUnit.Framework;


namespace INSTA.BankApplication.Engine.Tests
{
    [TestFixture]
    public class Test_AccountBase
    {
        AccountBase     _account;
        Customer        _holder;
        double          _amount;

        private MoneyTransferEventArgs _args = null;

        [SetUp]
        public void SetUp()
        {
            _amount     = AccountFactory.MIN_DEPOSIT_STANDARD;
            _holder     = new Customer();            
            _account    = Bank.Instance().CreateAccount(_holder, _amount);
            _args       = null;
        }


        [Test]
        public void Test_Event_MoneyTransferred_ForDeposit()
        {
            // make a method subscribe to the event..
            _account.MoneyTransferred += OnDepositTransfer;

            // Let's make a deposit in order to fire the event..
            _account.Deposit(10);

            bool result = false;

            result = _args.TransferType == TransferType.Deposit;
            result = result && _args.TransferAmount == 10;
            result = result && _account.Balance == AccountFactory.MIN_DEPOSIT_STANDARD + 10;

            Assert.IsTrue(result);

        }

        private void OnDepositTransfer(object sender, MoneyTransferEventArgs e)
        {
            _args = e;
        }

        [Test]
        public void Test_Event_MoneyTransferred_ForWithdraw()
        {
            // make a method subscribe to the event..
            _account.MoneyTransferred += OnWithdrawTransfer;

            // Let's make a deposit in order to fire the event..
            _account.Withdraw(10);

            bool result = false;

            result = _args.TransferType == TransferType.Withdraw;
            result = result && _args.TransferAmount == 10;
            result = result && _account.Balance == AccountFactory.MIN_DEPOSIT_STANDARD - 10;

            Assert.IsTrue(result);

        }

        private void OnWithdrawTransfer(object sender, MoneyTransferEventArgs e)
        {
            _args = e;
        }










        [Test]
        public void Test_Constructor_ForHolder()
        {
            _account = Bank.Instance().CreateAccount(_holder, AccountFactory.MIN_DEPOSIT_STANDARD + 1);
            Assert.AreSame(_holder, _account.Holder);
        }

        [Test]
        public void Test_Constructor_ForDeposit_Positive()
        {
            _account = Bank.Instance().CreateAccount(_holder, AccountFactory.MIN_DEPOSIT_STANDARD + 1);
            Assert.IsTrue(_account.Balance == AccountFactory.MIN_DEPOSIT_STANDARD + 1);
        }

        [Test]
        public void Test_Constructor_ForDeposit_Negative()
        {
            Assert.Throws<ArgumentException>(() => Bank.Instance().CreateAccount(_holder, -1));
        }

        [Test]
        public void Test_Method_Deposit_ForPositiveAmount()
        {
            _account.Deposit(1);
            Assert.IsTrue(_account.Balance == _amount + 1);
        }

        [Test]
        public void Test_Method_Deposit_ForNegativeAmount()
        {
            _account.Deposit(-1);
            Assert.IsTrue(_account.Balance == _amount);
        }

        [Test]
        public void Test_Method_Withdraw_ForPositiveAmount()
        {
            _account.Withdraw(1);
            Assert.IsTrue(_account.Balance == _amount - 1);
        }

        [Test]
        public void Test_Method_Withdraw_ForNegativeAmount()
        {
            _account.Withdraw(-1);
            Assert.IsTrue(_account.Balance == _amount);
        }

        [Test]
        public void Test_Property_IsAccountExcessOverdrawn_ForFalse()
        {
            double maxOverdrawn = _account.GetMaxOverdrawn();

            _account.Withdraw(_amount + maxOverdrawn - 1);

            Assert.IsFalse(_account.IsAccountExcessOverdrawn);
        }

        [Test]
        public void Test_Property_IsAccountExcessOverdrawn_ForTrue()
        {
            double maxOverdrawn = _account.GetMaxOverdrawn();

            _account.Withdraw(_amount + maxOverdrawn + 1);

            Assert.IsTrue(_account.IsAccountExcessOverdrawn);
        }

    }
}
